/*
 * Copyright (c) 2010-2011 Josef Hardi <josef.hardi@gmail.com>
 * Copyright (c) 2010 Piotr Zagawa <piotr.zagawa@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package id.duapuluhdua.dakidaki.ui;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.MotionEvent;

import id.duapuluhdua.dakidaki.common.CommonActivity;
import id.duapuluhdua.dakidaki.map.Screen;


/**
 *
 */
public abstract class UIElement
{
  /** Constants */
  protected static final float TEXT_SKEW = -0.2f;

  /** Fields */
  protected CommonActivity mParent;
  protected Screen mScreen;
  protected DisplayMetrics mMetrics;

  private Handler mClickHandler;

  private Paint mBackgroundShadow;
  protected Paint mDefaultText;

  protected UIElementStyle mStyle;

  protected static int screenWidth = 0;
  protected static int screenHeight = 0;

  protected RectF mRtBackground;
  protected RectF mRtBackgroundShadow;
  protected Rect mRtBounds;

  private Boolean bPressedDown = false;

  protected boolean bAlwaysVisible = false;

  /**
   * The default constructor.
   *
   * @param parent
   * @param screen
   */
  public UIElement(CommonActivity parent, Screen screen)
  {
    mParent = parent;
    mScreen = screen;
    mMetrics = parent.getResources().getDisplayMetrics();

    mRtBackground = new RectF(0, 0, 0, 0);
    mRtBackgroundShadow = new RectF(0, 0, 0, 0);
    mRtBounds = new Rect(0, 0, 0, 0);

    mStyle = new UIElementStyle();

    mDefaultText = new Paint();
    mDefaultText.setAntiAlias(true);
    mDefaultText.setARGB(255, 0, 0, 0);

    mBackgroundShadow = new Paint();
    mBackgroundShadow.setAntiAlias(true);

    mClickHandler = new Handler();

    updateStyle();
  }

  /**
   *
   * @param cs
   */
  public void doDraw(Canvas canvas)
  {
    mRtBackground.set(mRtBounds);
    mRtBackground.inset(-mStyle.backgroundMargin, -mStyle.backgroundMargin);

    mRtBackground.left += mStyle.rtBackgroundMarginCorrect.left;
    mRtBackground.right += mStyle.rtBackgroundMarginCorrect.right;
    mRtBackground.top += mStyle.rtBackgroundMarginCorrect.top;
    mRtBackground.bottom += mStyle.rtBackgroundMarginCorrect.bottom;
  }

  /**
   * Return whether the UI element is in the pressed area.
   *
   * @param event the finger touching event.
   * @return true if the UI element receives a pressed event within its touch
   * area, or false otherwise.
   */
  public boolean isInTouchArea(MotionEvent event)
  {
    return mRtBackground.contains(event.getX(), event.getY());
  }

  /**
   * Set the pressed status.
   */
  protected void setPressed()
  {
    synchronized(bPressedDown)
    {
      bPressedDown = true;
    }
  }

  /**
   * Return whether the UI element has been pressed or not.
   *
   * @return true if the UI element receives a pressed event, or false
   * otherwise.
   */
  public boolean isPressedDown()
  {
    synchronized(bPressedDown)
    {
      return bPressedDown;
    }
  }

  /**
   * Remove the pressed status.
   */
  public void clearPressed()
  {
    synchronized(bPressedDown)
    {
      bPressedDown = false;
    }
  }

  /**
   * Signal the clicking event to an action.
   */
  public void doClick()
  {
    mClickHandler.removeCallbacks(mTaskDoClick);
    mClickHandler.post(mTaskDoClick);
  }

  private Runnable mTaskDoClick = new Runnable() {
    @Override
    public void run()
    {
      synchronized(mClickHandler)
      {
        onClick();
      }
    }
  };

  /**
   * Set the position of the drawing graphic.
   *
   * @param left
   * @param top
   */
  public void setPos(int left, int top)
  {
    mRtBounds.offsetTo(left, top);
  }

  /**
   * Set the width and height measure for the drawing graphic.
   *
   * @param width the width size.
   * @param height the height size.
   */
  public void setSize(int width, int height)
  {
    mRtBounds.right = mRtBounds.left + width;
    mRtBounds.bottom = mRtBounds.top + height;
  }

  public void updateObjectsState()
  {
    // Do nothing!
  }

  /**
   * Draw a dark grey surround the rectangle.
   *
   * @param canvas
   *            The canvas object.
   * @param round
   *            The radius to draw the round corner.
   */
  protected void drawSimpleShadow(Canvas canvas, float round)
  {
    mBackgroundShadow.setColor(0xffdddddd);
    mRtBackgroundShadow.set(mRtBackground);
    mRtBackgroundShadow.inset(-2, -2);
    canvas.drawRoundRect(mRtBackgroundShadow, round, round, mBackgroundShadow);
  }

  /**
   * Convert the dps to pixels.
   *
   * @param dips
   * @return
   */
  protected float toPixel(float dips)
  {
    if (mMetrics.densityDpi == DisplayMetrics.DENSITY_LOW) {
      return (dips * mMetrics.density) - 0.5f;  // decrease more if low density
    }
    return (dips * mMetrics.density) + 0.5f;
  }

  public void updateStyle()
  {
    // Do nothing.
  }

  // Implements the action when the element is clicked.
  public abstract void onClick();

  // Implements the action when the surface size changes.
  public abstract void surfaceSizeChanged(int width, int height, int screenOrientation);
}
